﻿using System;
using System.Drawing;
using System.Windows.Forms;
using GeoSketch2.Core;
using System.Diagnostics;
using System.IO;

namespace GeoSketch2.Archaeo
{
    /// <summary>
    /// The form to draw of the Archaeo module
    /// </summary>
    public partial class DrawingForm : GeoSketchForm
    {
        string ProjectFilename;

        #region Constructor
        /// <summary>
        /// The form to draw of the Archaeo module
        /// </summary>
        /// <param name="MDIParentForm">The parent form</param>
        /// <param name="Site">The current excavation site</param>
        /// <param name="ProjectFilename">The file name of the project, for saving purpose</param>
        public DrawingForm(Form MDIParentForm, ArchaeoProject Project,string ProjectFilename)
            : base(new ActiveMDIParentItems(true,true,true,false,false,false,false,false,false,false,false), MDIParentForm)
        {
            InitializeComponent();
            this.ChildMenuStrip.Visible = false;
            this.ProjectFilename = ProjectFilename;

            MergeToolbars();
            MergeStatusStrips();

            DisplayBox.LeftClicTool = new TNone();
            StatusStripLeftClicToolTextBox.Tag = DisplayBox.LeftClicTool;
            DisplayBox.RightClicTool = new TNone();
            StatusStripRightClicToolTextBox.Tag = DisplayBox.RightClicTool;

            DisplayBox.Viewport = new Viewport(DisplayBox, Project);
            SetupForm(toolbarsToolStripMenuItem);
            LoadLayers();
            LoadColors();
            LoadLineTypeLibrary();
            LoadSiteHierarchy();
            SetFormTitle();

            DisplayBox.MouseMove += new MouseEventHandler(DisplayBox_MouseMove);
            SiteHierarchy.AfterLabelEdit += new NodeLabelEditEventHandler(SiteHierarchy_AfterLabelEdit);
            StatusStripLeftClicToolTextBox.KeyPress += new KeyPressEventHandler(StatusStripToolTextBox_KeyPress);
            StatusStripRightClicToolTextBox.KeyPress += new KeyPressEventHandler(StatusStripToolTextBox_KeyPress);
            DropDown_LineType.Paint += new PaintEventHandler(Label_LineType_Paint);
            this.Activated += new EventHandler(DrawingForm_Activated);
            this.Deactivate += new EventHandler(DrawingForm_Deactivate);

            this.WindowState = FormWindowState.Maximized;

            SetToolbarsLocation();
        }

        private void SetToolbarsLocation()
        {
            int top = ChildToolbar.Top + 3;
            foreach (Control c in this.Controls)
            {
                if (c.GetType().BaseType == typeof(BaseToolbar))
                {
                    c.Left = Screen.PrimaryScreen.WorkingArea.Width - c.Width - 6;
                    c.Top = top;
                    top = c.Bottom + 3;
                }
            }
        }
        #endregion

        #region Events
        #region Toolbar
        void MoreColorsMenuClick(object sender, MouseEventArgs e)
        {
            ColorDialog color_dialog = new ColorDialog();
            color_dialog.ShowDialog();

            DisplayBox.Viewport.CurrentColor = color_dialog.Color;
            DropDown_Color.Image = Tools.GetColoredSquare(color_dialog.Color, Core.Vars.Setup.StandardObjects.Layer.MenuItemsImageSize);
            DropDown_Color.Text = color_dialog.Color.Name;
        }

        void ColorMenuItemClick(object sender, MouseEventArgs e)
        {
            ToolStripMenuItem item = (ToolStripMenuItem)sender;

            DropDown_Color.Image = item.Image;
            DropDown_Color.Text = item.Text;

            DisplayBox.Viewport.CurrentColor = (Color)item.Tag;
            
            foreach (BaseDrawableObject obj in DisplayBox.Viewport.SelectedObjects)
            {
                obj.Color = (Color)item.Tag;
            }
        }

        void MoreLayersMenuClick(object sender, MouseEventArgs e)
        {
            throw new NotImplementedException();
        }

        void LayerMenuItemClick(object sender, MouseEventArgs e)
        {
            ToolStripMenuItem item = (ToolStripMenuItem)sender;

            if (e.Button == MouseButtons.Left)
            {
                DropDown_Layers.Image = item.Image;
                DropDown_Layers.Text = item.Text;

                DisplayBox.Viewport.CurrentLayer = (Layer)item.Tag;
                
                foreach (BaseDrawableObject obj in DisplayBox.Viewport.SelectedObjects)
                {
                    obj.Layer = (Layer)item.Tag;
                }
                
                SetByLayerColor();
                DropDown_LineType.Tag = null;
                DropDown_LineType.Invalidate();
            }
            else if (e.Button == MouseButtons.Right)
            {
                item.Checked = !item.Checked;
                ((Layer)item.Tag).Visible = item.Checked;

                if (item.Checked)
                {
                    item.Image = ((Layer)item.Tag).MenuItemImageVisible;
                    item.ForeColor = SystemColors.ControlText;
                }
                else
                {
                    item.Image = ((Layer)item.Tag).MenuItemImageInvisible;
                    item.ForeColor = Core.Vars.Setup.StandardObjects.Layer.MenuItemsLayerInvisible;
                }
            }
        }

        private void ManageLayersMenuItemClick(object sender, EventArgs e)
        {
            LayersManager alm = new LayersManager(this.MdiParent, DisplayBox.Viewport, this);
            alm.Show();
        }

        void Button_ToggleSiteHirearchy_Click(object sender, EventArgs e)
        {
            SiteHierarchy.Visible = !SiteHierarchy.Visible;
        }

        void Label_LineType_Paint(object sender, PaintEventArgs e)
        {
            ToolStripDropDownButton s = ((ToolStripDropDownButton)sender);
            if (s.Tag != null)
            {
                e.Graphics.DrawImage(((LineType)s.Tag).ImageOverview(s.Size), 0, 0);
            }
            else
            {
                e.Graphics.DrawString("ByLayer", DropDown_LineType.Font, new SolidBrush(DropDown_LineType.ForeColor), 1, 5);
                e.Graphics.DrawImage(DisplayBox.Viewport.CurrentLayer.LineType.ImageOverview(s.Size), 45, 0);
            }
        }

        private void Button_SurveyLogBook_Click(object sender, EventArgs e)
        {
            SurveyLogBookForm form = new SurveyLogBookForm(DisplayBox.Viewport.CurrentExcavationArea);
            form.Show();
        }

        private void Button_SoilSheet_Click(object sender, EventArgs e)
        {
            DisplayBox.Viewport.CurrentExcavationArea.SoilSheet.ShowForm();
        }

        void LineTypeLibraryMenuItemClick(object sender, EventArgs e)
        {
            ToolStripMenuItem item = (ToolStripMenuItem)sender;

            DropDown_LineType.Tag = item.Tag;

            DisplayBox.Viewport.CurrentLineType = (LineType)item.Tag;

            foreach (BaseDrawableObject obj in DisplayBox.Viewport.SelectedObjects)
            {
                obj.LineType = (LineType)item.Tag;
            }

            DisplayBox.Refresh();
            DropDown_LineType.Invalidate();
        }

        void ByLayerMenuItemPaint(object sender, PaintEventArgs e)
        {
            ToolStripMenuItem s = (ToolStripMenuItem)sender;
            e.Graphics.DrawString("ByLayer", DropDown_LineType.Font, new SolidBrush(DropDown_LineType.ForeColor), 1, 5);
            e.Graphics.DrawImage(DisplayBox.Viewport.CurrentLayer.LineType.ImageOverview(s.Size), 45, 0);
        }

        private void toolStripButton1_Click(object sender, EventArgs e)
        {
            ExcavationAreaInfoForm form = new ExcavationAreaInfoForm(DisplayBox.Viewport);
            form.ShowDialog();
        }
        #endregion

        #region Status strip
        //Action when pressing the return key in a textbox of a tool
        void StatusStripToolTextBox_KeyPress(object sender, KeyPressEventArgs e)
        {
            if (e.KeyChar == (char)Keys.Return)
            {
                ((ToolStripDropDownButton)((ToolStripTextBox)sender).OwnerItem).HideDropDown();
                ((BaseTool)((ToolStripTextBox)sender).Tag).TextEntry(((ToolStripTextBox)sender).Text);
                ((ToolStripTextBox)sender).Text = "";
            }
        } 
        #endregion

        #region Treeview of site hierarchy
        //Edition of a label in the treeview
        void SiteHierarchy_AfterLabelEdit(object sender, NodeLabelEditEventArgs e)
        {
            ((ExcavationArea)e.Node.Tag).Name = e.Label;
            DisplayBox.Refresh();
        }

        void SiteHierarchy_MouseDoubleClick(object sender, MouseEventArgs e)
        {
            if (SiteHierarchy.SelectedNode != null)
            {
                DisplayBox.Viewport.CurrentExcavationArea = (ExcavationArea)SiteHierarchy.SelectedNode.Tag;
                LoadLayers();
                LoadColors();
                SetFormTitle();
                Button_ToggleSiteHirearchy_Click(null, null);
                DisplayBox.Refresh();
            }
        }
        #endregion

        #region Displaybox
        //Action of a mouse move on the display box, displays the object coordinates
        void DisplayBox_MouseMove(object sender, MouseEventArgs e)
        {
            Point2D64D MouseObjectCoordinates = DisplayBox.Viewport.Object2ImageTransformation.InverseTransform(e.Location);
            Label_XY.Text = "X=" + MouseObjectCoordinates.X.ToString("F3",Core.Vars.Setup.GeoSketch.NumberFormat) + " ; Y=" + MouseObjectCoordinates.Y.ToString("F3",Core.Vars.Setup.GeoSketch.NumberFormat);
        } 
        #endregion

        #region Form
        void DrawingForm_Deactivate(object sender, EventArgs e)
        {
            RevertMergeToolbars();
            RevertMergeStatusStrips();
        }

        void DrawingForm_Activated(object sender, EventArgs e)
        {
            MergeToolbars();
            MergeStatusStrips();
        } 
        #endregion
        #endregion

        #region Methods
        /// <summary>
        /// The method which loads the layers to the toolbar
        /// </summary>
        public void LoadLayers()
        {
            DropDown_Layers.DropDownItems.Clear();
            int LayerToDisplayCount = Math.Min(DisplayBox.Viewport.CurrentExcavationArea.AvailableLayers.Count, Vars.Setup.Forms.DrawingForm.MaxLayersToDisplay);
            bool CurrentLayerFound = false;

            DisplayBox.Viewport.CurrentExcavationArea.AvailableLayers.Sort(Layer.CompareLayerDisplayOrderDesc);
            for (int i = 0; i < LayerToDisplayCount; i++)
            {
                ToolStripMenuItem item = DisplayBox.Viewport.CurrentExcavationArea.AvailableLayers[i].MenuItem;
                item.Checked = true;
                item.MouseDown += new MouseEventHandler(LayerMenuItemClick);
                DropDown_Layers.DropDownItems.Add(item);
                if (!DisplayBox.Viewport.CurrentExcavationArea.AvailableLayers[i].Visible)
                {
                    LayerMenuItemClick(item, new MouseEventArgs(MouseButtons.Right, 0, 0, 0, 0));
                }
                if (DisplayBox.Viewport.CurrentLayer != null)
                {
                    if (DisplayBox.Viewport.CurrentExcavationArea.AvailableLayers[i].Name == DisplayBox.Viewport.CurrentLayer.Name)
                    {
                        LayerMenuItemClick(item, new MouseEventArgs(MouseButtons.Left, 0, 0, 0, 0));
                        CurrentLayerFound = true;
                    }
                }

            }
            DisplayBox.Viewport.CurrentExcavationArea.AvailableLayers.Sort(Layer.CompareLayerDisplayOrderAsc);

            if (DisplayBox.Viewport.CurrentExcavationArea.AvailableLayers.Count > Vars.Setup.Forms.DrawingForm.MaxLayersToDisplay)
            {
                ToolStripMenuItem item = new ToolStripMenuItem("More layers...");
                item.MouseDown += new MouseEventHandler(MoreLayersMenuClick);
                DropDown_Layers.DropDownItems.Add(item);
            }

            if (!CurrentLayerFound)
            {
                LayerMenuItemClick(DropDown_Layers.DropDownItems[0], new MouseEventArgs(MouseButtons.Left, 0, 0, 0, 0));
            }
        }

        /// <summary>
        /// The method which loads the colors to the toolbar
        /// </summary>
        public void LoadColors()
        {
            DropDown_Color.DropDownItems.Clear();

            ToolStripMenuItem item = new ToolStripMenuItem("ByLayer", Tools.GetColoredSquare(DisplayBox.Viewport.Layers[0].LayerColor, Core.Vars.Setup.StandardObjects.Layer.MenuItemsImageSize));
            item.MouseDown += new MouseEventHandler(ColorMenuItemClick);
            item.Tag = BaseDrawableObject.ColorByLayer();
            DropDown_Color.DropDownItems.Add(item);

            foreach (Color color in Vars.Setup.Forms.DrawingForm.MenuColors)
            {
                item = new ToolStripMenuItem(color.Name, Tools.GetColoredSquare(color, Core.Vars.Setup.StandardObjects.Layer.MenuItemsImageSize));
                item.MouseDown += new MouseEventHandler(ColorMenuItemClick);
                item.Tag = color;
                DropDown_Color.DropDownItems.Add(item);
            }

            item = new ToolStripMenuItem("More colors...");
            item.MouseDown += new MouseEventHandler(MoreColorsMenuClick);
            DropDown_Color.DropDownItems.Add(item);

            SetByLayerColor();
        }

        /// <summary>
        /// Loads the linetype library
        /// </summary>
        public void LoadLineTypeLibrary()
        {
            DropDown_LineType.DropDownItems.Clear();

            ToolStripMenuItem item = LineTypeByLayerMenuItem;

            item.Click += new EventHandler(LineTypeLibraryMenuItemClick);
            DropDown_LineType.DropDownItems.Add(item);

            foreach (LineType l in DisplayBox.Viewport.LineTypeLibrary)
            {
                item = l.MenuItem;
                
                item.Click += new EventHandler(LineTypeLibraryMenuItemClick);
                DropDown_LineType.DropDownItems.Add(item);
            }
            
            LineTypeLibraryMenuItemClick(DropDown_LineType.DropDownItems[0], null);
        }

        /// <summary>
        /// The method which loads the site hierarchy ont the treeview
        /// </summary>
        public void LoadSiteHierarchy()
        {
            SiteHierarchy.Nodes.Clear();

            SiteHierarchy.Nodes.Add(DisplayBox.Viewport.Project.MainSite.TreeViewNode);

            SiteHierarchy.MouseDoubleClick += new MouseEventHandler(SiteHierarchy_MouseDoubleClick);
        }

        //Sets the title of the form accroding to the current excavation area
        internal void SetFormTitle()
        {
            this.Text = DisplayBox.Viewport.CurrentExcavationArea.Path;
        }

        //Set the current color to ByLayer
        private void SetByLayerColor()
        {
            if (DropDown_Color.DropDownItems.Count > 0)
            {
                DropDown_Color.DropDownItems[0].Image = Tools.GetColoredSquare(DisplayBox.Viewport.CurrentLayer.LayerColor, Core.Vars.Setup.StandardObjects.Layer.MenuItemsImageSize);
                ColorMenuItemClick(DropDown_Color.DropDownItems[0], null);
            }
        }

        /// <summary>
        /// The method to merge the toolbar of the form to the main's one
        /// </summary>
        public void MergeToolbars()
        {
            ToolStripManager.Merge(ChildToolbar, ParentToolbar);
            ChildToolbar.Visible = false;
        }

        /// <summary>
        /// The method to merge the status strip of the form to the main's one
        /// </summary>
        public void MergeStatusStrips()
        {
            ToolStripManager.Merge(statusStrip1, ParentStatusBar);
            statusStrip1.Visible = false;
        }

        /// <summary>
        /// The method to revert merge the toolbar of the form to the main's one
        /// </summary>
        public void RevertMergeToolbars()
        {
            ToolStripManager.RevertMerge(ParentToolbar,ChildToolbar );
        }

        /// <summary>
        /// The method to revert merge the status strip of the form to the main's one
        /// </summary>
        public void RevertMergeStatusStrips()
        {
            ToolStripManager.RevertMerge(ParentStatusBar, statusStrip1);
        }

        /// <summary>
        /// The action when clicking the save as button or menu
        /// </summary>
        public override void MDIParentSaveAs()
        {
            SaveFileDialog sfd = new SaveFileDialog();
            sfd.Filter = Vars.Setup.FileIO.GSK.OpenSaveDialogDefaultExtensionFilter;
            DialogResult dr = sfd.ShowDialog();
            if (dr == DialogResult.OK)
            {
                this.ProjectFilename = sfd.FileName;
                DisplayBox.Viewport.Project.SaveToGSK(sfd.FileName);
                DisplayBox.Viewport.Project.ProjectDirectory = Path.GetDirectoryName(this.ProjectFilename);
            }
        }

        /// <summary>
        /// The action when clicking the save button or menu
        /// </summary>
        public override void MDIParentSave()
        {
            if (this.ProjectFilename != "")
            {
                DisplayBox.Viewport.Project.SaveToGSK(this.ProjectFilename);
                MessageBox.Show("Saved as " + this.ProjectFilename, "OK", MessageBoxButtons.OK, MessageBoxIcon.Information);
            }
            else
            {
                MDIParentSaveAs();
            }
        }
        #endregion

        #region Properties
        /// <summary>
        /// Gets the dropdown button on the status bar corresponding to the left clic tool 
        /// </summary>
        public override ToolStripDropDownItem StatusStripLeftClicToolDropDownButton
        {
            get
            {
                return _StatusStripLeftClicToolDropDown;
            }
        }

        /// <summary>
        /// Gets the textbox on the status bar corresponding to the left clic tool 
        /// </summary>
        public override ToolStripTextBox StatusStripLeftClicToolTextBox
        {
            get
            {
                return _StatusStripLeftClicToolTextBox;
            }
        }

        /// <summary>
        /// Gets the dropdown button on the status bar corresponding to the right clic tool 
        /// </summary>
        public override ToolStripDropDownItem StatusStripRightClicToolDropDownButton
        {
            get
            {
                return _StatusStripRightClicToolDropDown;
            }
        }

        /// <summary>
        /// Gets the textbox on the status bar corresponding to the right clic tool 
        /// </summary>
        public override ToolStripTextBox StatusStripRightClicToolTextBox
        {
            get
            {
                return _StatusStripRightClicToolTextBox;
            }
        }

        /// <summary>
        /// Gets the label on the status bar to display messages
        /// </summary>
        public override ToolStripLabel StatusStripLabel
        {
            get
            {
                return Label_ToolsMessage;
            }
        }

        /// <summary>
        /// Gets linetype bylayer menu item
        /// </summary>
        public ToolStripMenuItem LineTypeByLayerMenuItem
        {
            get
            {
                ToolStripMenuItem item = new ToolStripMenuItem();

                item.AutoSize = true;

                item.BackColor = Color.White;
                item.DisplayStyle = ToolStripItemDisplayStyle.Text;
                item.Width = 100;
                item.Tag = null;
                item.Paint += new PaintEventHandler(ByLayerMenuItemPaint);

                return item;
            }
        }
        #endregion

        private void saveAsDXFR13ToolStripMenuItem_Click(object sender, EventArgs e)
        {
            try
            {
                string DxfFilename = Path.GetDirectoryName(this.ProjectFilename) + "\\" + Path.GetFileNameWithoutExtension(this.ProjectFilename) + ".dxf";
                DialogResult dr = DialogResult.Yes;
                if (File.Exists(DxfFilename))
                {
                    dr = MessageBox.Show("File already exists, overwrite?", "Warning", MessageBoxButtons.YesNo, MessageBoxIcon.Warning, MessageBoxDefaultButton.Button2);
                }
                if (dr == DialogResult.Yes)
                {
                    FileIO.WriteDXFR13(this.DisplayBox.Viewport.Project, DxfFilename);
                    MessageBox.Show("Saved as " + DxfFilename, "OK", MessageBoxButtons.OK, MessageBoxIcon.Information);
                }
                else
                {
                    saveAsDXFR13ToolStripMenuItem1_Click(sender, e);
                }
            }
            catch
            {
                MessageBox.Show("Check if file is already opened", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }

        }

        private void saveAsDXFR13ToolStripMenuItem1_Click(object sender, EventArgs e)
        {
            SaveFileDialog sfd = new SaveFileDialog();
            sfd.Filter = "Dxf R13 files (*.dxf)|*.dxf|All files (*.*)|*.*";
            sfd.CheckFileExists = true;
            DialogResult dr = sfd.ShowDialog();

            if (dr == DialogResult.OK)
            {
                try
                {
                    string DxfFilename = Path.GetDirectoryName(sfd.FileName) + "\\" + Path.GetFileNameWithoutExtension(sfd.FileName) + ".dxf";
                    FileIO.WriteDXFR13(this.DisplayBox.Viewport.Project, DxfFilename);
                    MessageBox.Show("Saved as " + DxfFilename, "OK", MessageBoxButtons.OK, MessageBoxIcon.Information);
                }
                catch
                {
                    MessageBox.Show("Check if file is already opened", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
                }
            }
        }
    }
}
